let sigmoid x =
  1. /. (1.+.exp(-.x))

let dersigmoid x =
  x*.(1.-.x)

let weightText weightList =
  begin
    if(Sys.file_exists "weights") then
      begin
	let file = open_in "weights" in
	for i = 0 to 26299 do
	  begin
	    weightList.(i) <- float_of_string(input_line file);
	  end
	done;
	close_in file;
      end
    else
      begin
	let file = open_out "weights" in
	for i = 0 to 26299 do
	  begin
	    weightList.(i) <- (Random.float 1.)-.0.5;
	    output_string file (string_of_float(weightList.(i)));
            output_string file "\n";
	  end
	done;
	close_out file;
      end
  end

let writeWeight weightList =
  begin
    let file = open_out "weights" in
    for i = 0 to 26299 do
      begin
	output_string file (string_of_float(weightList.(i)));
	output_string file "\n";
      end;
    done;
    close_out file;
  end

let rec populateInput img inputNeurons =
  begin
    for j = 0 to 19 do
      for i = 0 to 19 do
	begin
  	  if(Preprocess.get (i,j,img) <= 127) then
  	    begin
  	      inputNeurons.(j*20+i) <- 1.;
 	    end
 	  else
  	    begin
 	      inputNeurons.(j*20+i) <- 0.;
 	    end;
	end;
      done;
    done;
  end

let network img target learning =
  let inputNeurons = Array.make 400 0. in
  let hiddenNeurons = Array.make 150 0. in
  let outputNeurons = Array.make 26 0. in
  let hdelta = Array.make 150 0. in
  let odelta = Array.make 26 0. in
  let weight = Array.make 26300 0. in
  let ascii = ref (-1) in
  begin
    weightText weight;
    populateInput img inputNeurons;
    for i = 0 to 49 do
      for j = 0 to 399 do
	hiddenNeurons.(i) <- hiddenNeurons.(i) +.
 (weight.(i*400+j)*.inputNeurons.(j));
      done;
      hiddenNeurons.(i) <- sigmoid(hiddenNeurons.(i));
    done;
    for i = 0 to 1 do
      for j = 0 to 49 do
	for k = 0 to 49 do
	  hiddenNeurons.(50*(i+1)+j) <- hiddenNeurons.(50*(i+1)+j) +.
 (weight.(i*2500+j*50+k+20000)*.hiddenNeurons.(i*50+k));
	done;
	hiddenNeurons.(50*(i+1)+j) <- sigmoid(hiddenNeurons.(50*(i+1)+j));
      done;
    done;
    for i = 0 to 25 do
      for j = 0 to 49 do
	outputNeurons.(i) <- outputNeurons.(i) +.
 (weight.(i*50+j+25000))*.hiddenNeurons.(100+j);
      done;
      outputNeurons.(i) <- sigmoid(outputNeurons.(i));
    done;
    if (not(learning)) then
      begin
	let value = ref (-1.) in
	for i = 0 to 25 do
	  begin
	    if (outputNeurons.(i) > !value) then
	      begin
		ascii := i;
		value := outputNeurons.(i);
	      end
	  end
	done;
      end
    else
      begin
	for i = 0 to 25 do
	  if i != target then
	    begin
	      odelta.(i) <-
 (0.-.outputNeurons.(i))*.(dersigmoid(outputNeurons.(i)));
	    end
	  else
	    begin
	      odelta.(i) <-
 (1.-.outputNeurons.(i))*.(dersigmoid(outputNeurons.(i)));
	    end
	done;
	for i = 0 to 49 do
	  for j = 0 to 25 do
	    hdelta.(i+100) <- hdelta.(i+100) +.
 odelta.(j)*.(weight.(j*50+i+25000));
	  done;
	  hdelta.(i+100) <- hdelta.(i+100) *.
 dersigmoid(hiddenNeurons.(100+i));
	done;
	for i = 1 downto 0 do
	  for j = 0 to 49 do
	    for k = 0 to 49 do
	      hdelta.(50*i+j) <- hdelta.(50*i+j) +.
 hdelta.(50*(i+1)+k)*.(weight.(i*2500+k*50+j+20000));
	    done;
	    hdelta.(50*i+j) <- hdelta.(50*i+j) *.
 dersigmoid(hiddenNeurons.(50*i+j));
	  done;
	done;
	(*weight modification*)
	for i = 0 to 399 do
	  for j = 0 to 49 do
	    weight.(j*400+i) <- weight.(j*400+i) +. (0.5 *. hdelta.(j) *.
 inputNeurons.(i));
	  done;
	done;
	for i = 0 to 1 do
	  for j = 0 to 49 do
	    for k = 0 to 49 do
	      weight.(i*2500+k*50+j+20000) <- weight.(i*2500+k*50+j+20000) +.
 (0.5 *. hdelta.(50*i+k) *. hiddenNeurons.(i*50+j));
	    done;
	  done;
	done;
	for i = 0 to 25 do
	  for j = 0 to 49 do
	    weight.(i*50+j+25000) <- weight.(i*50+j+25000) +. (0.5
 *.odelta.(i)*.hiddenNeurons.(100+j));
	  done;
	done;
	writeWeight weight;
      end
  end;
  !ascii
